home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / applic / ntp / kent.shar / des.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-29  |  10.3 KB  |  365 lines

  1. /* des.c -- this file contains an optimized C-based DES algorithm       */
  2. /* implementation.  Many loops are stretched out into straight-line code, */
  3. /* so this version is not particularly short, modular, or readable.  (size */
  4. /* as of 31 Aug 83:  7338+1426+6372 = 15136b = 035440b) However, it is */
  5. /* quick.  (A DES encryption times at approximately 7 user ms on a C/70) It */
  6. /* reads its key schedule and certain tables from files generated by */
  7. /* associated programs ksb.c and tblbld.c.  John Linn -- 8 April 1983 */
  8. /* "Bug" fix 17 Feb 1984 - insert masking so as to have E work on
  9.    32 bit machines with sign extension on right shifts (like Vax, 68k (?)) */
  10. /* observation: when compiled onto vax, takes only ~ 2.6 ms to encrypt */
  11.  
  12. #include <stdio.h>
  13. #define LMASK    0XFCFCFCFCL;
  14.  
  15. /* data structures to be read from files */
  16. static long ip [2] [256];     
  17. static long ipi [2] [256];
  18. static long snop [8] [64];
  19. unsigned ks [16] [4];
  20.  
  21. /* rdfiles -- reads filed info, returns 1 iff success, 0 otherwise */
  22. int rdfiles ()
  23. {
  24.   int i, j;
  25.   FILE *fp, *fopen ();
  26.  
  27.   if (NULL == (fp = fopen ("ip", "r")))
  28.   {
  29.     printf ("des -- can't read file 'ip'\n");
  30.     return (0);
  31.   }
  32.   for (i = 0; i < 2; i++)
  33.     for (j = 0; j < 256; j++) 
  34.       if (EOF == fscanf (fp, "%lx", &ip [i] [j]))
  35.       {
  36.         printf ("des -- 'ip' read failed at i=%d, j=%d\n", i, j);
  37.     return (0);
  38.       }
  39.   fclose (fp);
  40.   
  41.   if (NULL == (fp = fopen ("ipi", "r")))
  42.   {
  43.     printf ("des -- can't read file 'ipi'\n");
  44.     return (0);
  45.   }
  46.   for (i = 0; i < 2; i++)
  47.     for (j = 0; j < 256; j++) 
  48.       if (EOF == fscanf (fp, "%lx", &ipi [i] [j]))
  49.       {
  50.     printf ("des -- 'ipi' read failed at i=%d, j=%d\n", i, j);
  51.     return (0);
  52.       }
  53.   fclose (fp);
  54.   
  55.   if (NULL == (fp = fopen ("snop", "r")))
  56.   {
  57.     printf ("des -- can't read file 'snop'\n");
  58.     return (0);
  59.   }
  60.   for (i = 0; i < 8; i++)
  61.     for (j = 0; j < 64; j++) 
  62.       if (EOF == fscanf (fp, "%lx", &snop [i] [j]))
  63.       {
  64.         printf ("des -- 'snop' read failed at i=%d, j=%d\n", i, j);
  65.     return (0);
  66.       }
  67.   fclose (fp);
  68.  
  69.   if (NULL == (fp = fopen ("ks", "r")))
  70.   {
  71.     printf ("des -- can't read file 'ks'\n");
  72.     return (0);
  73.   }
  74.   for (i = 0; i < 16; i++)
  75.     for (j = 0; j < 4; j++) 
  76.       if (EOF == fscanf (fp, "%x", &ks [i] [j]))
  77.       {
  78.     printf ("des -- 'ks' read failed at i=%d, j=%d\n", i, j);
  79.     return (0);
  80.       }
  81.   fclose (fp);
  82.   
  83.   return (1);   /* success */
  84. }
  85.  
  86. #define BINBLK  8       /* number of bytes in an encryption chunk */
  87. #define BINLNG  4       /* the number of bytes in 32 bits of a long */
  88.  
  89. /* doip -- use ip table to permute 64 bits from inar to outar */
  90. doip (inar, outar)      
  91. long    inar [2];
  92. long    outar [2];
  93. {
  94.   extern long ip [2] [256];
  95.  
  96.   outar [0] = outar [1] = 0L;
  97.  
  98.   outar [0] |= ip [0] [0XFF & inar [1]];
  99.   outar [1] |= ip [1] [0XFF & inar [1]];
  100.   outar [0] <<= 1;
  101.   outar [1] <<= 1;
  102.   outar [0] |= ip [0] [0XFF & (inar [1] >> 8)];
  103.   outar [1] |= ip [1] [0XFF & (inar [1] >> 8)];
  104.   outar [0] <<= 1;
  105.   outar [1] <<= 1;
  106.   outar [0] |= ip [0] [0XFF & (inar [1] >> 16)];
  107.   outar [1] |= ip [1] [0XFF & (inar [1] >> 16)];
  108.   outar [0] <<= 1;
  109.   outar [1] <<= 1;
  110.   outar [0] |= ip [0] [0XFF & (inar [1] >> 24)];
  111.   outar [1] |= ip [1] [0XFF & (inar [1] >> 24)];
  112.   outar [0] <<= 1;
  113.   outar [1] <<= 1;
  114.   outar [0] |= ip [0] [0XFF & inar [0]];
  115.   outar [1] |= ip [1] [0XFF & inar [0]];
  116.   outar [0] <<= 1;
  117.   outar [1] <<= 1;
  118.   outar [0] |= ip [0] [0XFF & (inar [0] >> 8)];
  119.   outar [1] |= ip [1] [0XFF & (inar [0] >> 8)];
  120.   outar [0] <<= 1;
  121.   outar [1] <<= 1;
  122.   outar [0] |= ip [0] [0XFF & (inar [0] >> 16)];
  123.   outar [1] |= ip [1] [0XFF & (inar [0] >> 16)];
  124.   outar [0] <<= 1;
  125.   outar [1] <<= 1;
  126.   outar [0] |= ip [0] [0XFF & (inar [0] >> 24)];
  127.   outar [1] |= ip [1] [0XFF & (inar [0] >> 24)];
  128. }
  129.  
  130. /* doipi -- use ipi to perform ip-inverse */
  131. /* doesn't use ipis table: knowledge of byte order is hardcoded */
  132. doipi (inar, outar)     
  133. long    inar [2];
  134. long    outar [2];
  135. {
  136.   extern long ipi [2] [256];
  137.  
  138.   outar [0] = outar [1] = 0L;
  139.  
  140.   outar [0] |= ipi [0] [0XFF & (inar [1] >> 24)];       /* "5" */
  141.   outar [1] |= ipi [1] [0XFF & (inar [1] >> 24)];
  142.   outar [0] <<= 1;
  143.   outar [1] <<= 1;
  144.   outar [0] |= ipi [0] [0XFF & (inar [0] >> 24)];       /* "1" */
  145.   outar [1] |= ipi [1] [0XFF & (inar [0] >> 24)];
  146.   outar [0] <<= 1;
  147.   outar [1] <<= 1;
  148.   outar [0] |= ipi [0] [0XFF & (inar [1] >> 16)];       /* "6" */
  149.   outar [1] |= ipi [1] [0XFF & (inar [1] >> 16)];
  150.   outar [0] <<= 1;
  151.   outar [1] <<= 1;
  152.   outar [0] |= ipi [0] [0XFF & (inar [0] >> 16)];       /* "2" */
  153.   outar [1] |= ipi [1] [0XFF & (inar [0] >> 16)];
  154.   outar [0] <<= 1;
  155.   outar [1] <<= 1;
  156.   outar [0] |= ipi [0] [0XFF & (inar [1] >> 8)];        /* "7" */
  157.   outar [1] |= ipi [1] [0XFF & (inar [1] >> 8)];
  158.   outar [0] <<= 1;
  159.   outar [1] <<= 1;
  160.   outar [0] |= ipi [0] [0XFF & (inar [0] >> 8)];        /* "3" */
  161.   outar [1] |= ipi [1] [0XFF & (inar [0] >> 8)];
  162.   outar [0] <<= 1;
  163.   outar [1] <<= 1;
  164.   outar [0] |= ipi [0] [0XFF & inar [1]];       /* "8" */
  165.   outar [1] |= ipi [1] [0XFF & inar [1]];
  166.   outar [0] <<= 1;
  167.   outar [1] <<= 1;
  168.   outar [0] |= ipi [0] [0XFF & inar [0]];       /* "4" */
  169.   outar [1] |= ipi [1] [0XFF & inar [0]];
  170. }
  171.  
  172. /* des_encrypt -- encrypt a block under key sched in ks */
  173. des_encrypt (inar, outar)   
  174. long    inar [2];
  175. long    outar [2];
  176. {
  177.   extern unsigned ks [16] [4];
  178.   extern long snop [8] [64];
  179.  
  180.   register int round, oddbit;
  181.   unsigned expan [4];   /* receives output of E transform */
  182.   long sbout, scopy, tlong;
  183.   long oarr [2];
  184.  
  185.   doip (inar, outar);
  186.  
  187.   for (round = 0; round < 16; round++)
  188.   {
  189.     sbout = 0L;
  190.  
  191.     tlong = outar [1];
  192.     oddbit = (int) (01 & tlong);
  193.     tlong >>= 1;
  194.     tlong &= 0X7FFFFFFFL;       /* defeat sign extend -- jl 17 feb 84 */
  195.     if (oddbit) tlong |= 0X80000000L;
  196.  
  197.     tlong &= LMASK;
  198.     expan [0] = (unsigned) (tlong >> 16);
  199.     expan [1] = (unsigned) tlong;
  200.  
  201.     tlong = outar [1];
  202.     oddbit = !! (tlong & 0X80000000L);
  203.     tlong <<= 3;
  204.     if (oddbit) tlong |= 04;
  205.     tlong &= LMASK;
  206.     expan [2] = (unsigned) (tlong >> 16);
  207.     expan [3] = (unsigned) tlong;
  208.  
  209.     /* this code bypasses the alternative of loop setup 
  210.        and resultant computation within the loop for speed */
  211.     expan [0] ^= ks [round] [0];
  212.     sbout |= snop [0] [0X3F & (expan [0] >> 10)];
  213.     sbout |= snop [1] [0X3F & (expan [0] >> 2)];
  214.     expan [1] ^= ks [round] [1];
  215.     sbout |= snop [2] [0X3F & (expan [1] >> 10)];
  216.     sbout |= snop [3] [0X3F & (expan [1] >> 2)];
  217.     expan [2] ^= ks [round] [2];
  218.     sbout |= snop [4] [0X3F & (expan [2] >> 10)];
  219.     sbout |= snop [5] [0X3F & (expan [2] >> 2)];
  220.     expan [3] ^= ks [round] [3];
  221.     sbout |= snop [6] [0X3F & (expan [3] >> 10)];
  222.     sbout |= snop [7] [0X3F & (expan [3] >> 2)];
  223.  
  224.     scopy = outar [0];
  225.     outar [0] = outar [1];
  226.     outar [1] = scopy ^ sbout;
  227.   }
  228.  
  229.   /* a final swap */
  230.   scopy = outar [0];
  231.   outar [0] = outar [1];
  232.   outar [1] = scopy;
  233.  
  234.   doipi (outar, oarr);  /* perform ip-inverse into temp copy */
  235.   outar [0] = oarr [0];
  236.   outar [1] = oarr [1];
  237. }
  238.  
  239. /* des_decrypt -- decrypt a block under key sched in ks */
  240. des_decrypt (inar, outar)   
  241. long    inar [2];
  242. long    outar [2];
  243. {
  244.   extern unsigned ks [16] [4];
  245.   extern long snop [8] [64];
  246.  
  247.   register int round, oddbit;
  248.   unsigned expan [4];   /* receives output of E transform */
  249.   long sbout, scopy, tlong;
  250.   long oarr [2];
  251.  
  252.   doip (inar, outar);
  253.  
  254.   for (round = 15; round >= 0; round--)
  255.   /* note that decryption selects schedule keys in opposite order */
  256.   {
  257.     sbout = 0L;
  258.  
  259.     tlong = outar [1];
  260.     oddbit = (int) (01 & tlong);
  261.     tlong >>= 1;
  262.     tlong &= 0X7FFFFFFFL;       /* defeat sign extend -- jl 17 feb 84 */
  263.     if (oddbit) tlong |= 0X80000000L;
  264.  
  265.     tlong &= LMASK;
  266.     expan [0] = (unsigned) (tlong >> 16);
  267.     expan [1] = (unsigned) tlong;
  268.  
  269.     tlong = outar [1];
  270.     oddbit = !! (tlong & 0X80000000L);
  271.     tlong <<= 3;
  272.     if (oddbit) tlong |= 04;
  273.     tlong &= LMASK;
  274.     expan [2] = (unsigned) (tlong >> 16);
  275.     expan [3] = (unsigned) tlong;
  276.  
  277.     /* this code bypasses the alternative of loop setup 
  278.        and resultant computation within the loop for speed */
  279.     expan [0] ^= ks [round] [0];
  280.     sbout |= snop [0] [0X3F & (expan [0] >> 10)];
  281.     sbout |= snop [1] [0X3F & (expan [0] >> 2)];
  282.     expan [1] ^= ks [round] [1];
  283.     sbout |= snop [2] [0X3F & (expan [1] >> 10)];
  284.     sbout |= snop [3] [0X3F & (expan [1] >> 2)];
  285.     expan [2] ^= ks [round] [2];
  286.     sbout |= snop [4] [0X3F & (expan [2] >> 10)];
  287.     sbout |= snop [5] [0X3F & (expan [2] >> 2)];
  288.     expan [3] ^= ks [round] [3];
  289.     sbout |= snop [6] [0X3F & (expan [3] >> 10)];
  290.     sbout |= snop [7] [0X3F & (expan [3] >> 2)];
  291.  
  292.     scopy = outar [0];
  293.     outar [0] = outar [1];
  294.     outar [1] = scopy ^ sbout;
  295.   }
  296.  
  297.   /* a final swap */
  298.   scopy = outar [0];
  299.   outar [0] = outar [1];
  300.   outar [1] = scopy;
  301.  
  302.   doipi (outar, oarr);  /* perform ip-inverse into temp copy */
  303.   outar [0] = oarr [0];
  304.   outar [1] = oarr [1];
  305. }
  306.  
  307. /* facilities for timing */
  308. struct tbuffer
  309. {
  310.   long proc_utime;
  311.   long proc_stime;
  312.   long child_utime;
  313.   long child_stime;
  314. };
  315. struct tbuffer t_before;
  316. struct tbuffer t_after;
  317.  
  318. main ()
  319. {
  320.   int itnum, i;
  321.   long plain [2], crypt [2], cprbuf [2];
  322.   long udiff, bitsdone, u_msec;
  323.  
  324.   /* begin by reading tables and key schedule from files */
  325.   printf ("Reading filed tables and key schedule...\n");
  326.   if (1 != rdfiles ())
  327.   {
  328.     printf ("des -- couldn't get tables or key schedule\n");
  329.     exit (1);
  330.   }
  331.  
  332.   printf ("Enter input to encrypt as two hex longs: ");
  333.   scanf ("%lx %lx", &plain [0], &plain [1]);
  334.   des_encrypt (plain, crypt);
  335.   printf ("Result of encryption: %lx %lx\n", crypt [0], crypt [1]);
  336.  
  337.   printf ("Enter number of test iterations [decimal]: ");
  338.   scanf ("%d", &itnum);
  339.  
  340.   times (&t_before);
  341.   for (i = 0; i < itnum; i++)   
  342.   {
  343.     des_encrypt (plain, crypt);
  344.     des_decrypt (crypt, cprbuf);
  345.     if ((plain [0] != cprbuf [0]) || (plain [1] != cprbuf [1]))
  346.     {
  347.       printf ("Encrypt and decrypt disagree -- aborting!!\n");
  348.       exit (1);
  349.     }
  350.   }
  351.   times (&t_after);
  352.   printf ("All encryptions and decryptions verified consistent\n");
  353.  
  354.   /* note: the following code won't work if one times a number
  355.      of encryptions that take less than one tick, as can occur
  356.      on a vax with a small number of tests */
  357.   udiff = t_after.proc_utime - t_before.proc_utime;
  358.   printf ("user 1/60 sec ticks = %ld\n", udiff);
  359.   bitsdone = 2 * (itnum * 64);
  360.   u_msec = (udiff * 1000) / 60;
  361.   printf ("%ld user msec/DES cycle\n", u_msec / ((long) 2 * itnum));
  362.   printf ("%ld bits/user second\n", (bitsdone * 1000) / u_msec);
  363. }
  364.  
  365.